package com.ruoyi.cmdb.util;

import com.ruoyi.cmdb.vo.ApacheCommondExecRes;
import com.ruoyi.cmdb.vo.ExecShellRes;
import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.ExecuteWatchdog;
import org.apache.commons.exec.PumpStreamHandler;
import org.apache.commons.io.output.ByteArrayOutputStream;

import java.io.*;

/**
 * 执行shell 工具类
 *
 */
public class ExecShell {
    private static BufferedReader output;
    private static BufferedReader error;
    private static Integer exitCode=0;
    private static String line;
	/**
    * ByApacheCommondExec
    */
    public static ExecShellRes ByApacheCommondExec(String commond)  {
        try {
            CommandLine commandLine = CommandLine.parse(commond); //使用它需要引入外部依赖
            DefaultExecutor executor = new DefaultExecutor();
            executor.setWatchdog(new ExecuteWatchdog(60000));//set timeout
            final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            final ByteArrayOutputStream errorStream = new ByteArrayOutputStream();
            PumpStreamHandler streamHandler = new PumpStreamHandler(new PrintStream(outputStream), new PrintStream(errorStream));
            executor.setStreamHandler(streamHandler);
            exitCode = executor.execute(commandLine);
            output = new BufferedReader(new StringReader(outputStream.toString()));
            // while ((line = reader.readLine()) != null) {
            //     if (line.contains("sql")) {
            //         System.out.println(line);
            //     }
            // }

            error = new BufferedReader(new StringReader(errorStream.toString()));
            //if ((line = error.readLine()) != null) {
            //    System.err.println("Command error:");
            //    System.err.println(error);
            //}
            if (exitCode != 0) {
                System.out.println("Command execution failed with exit code: " + exitCode);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new ExecShellRes(output,error,exitCode);
    }

    //use runtime.exec() exec shell commond
    /**
     * ByRuntime
     */
    public static ExecShellRes ByRuntime(String commond)  {
        try {
            Process process = Runtime.getRuntime().exec(commond);
            output = new BufferedReader(new InputStreamReader(process.getInputStream()));

            //while ((line = output.readLine()) != null) {
            //    System.out.println(line);
            //}

            error = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            //if ((line = error.readLine()) != null){
            //    System.out.println("sout error:");
            //    while ((line = error.readLine()) != null) {
            //        System.out.println(line);
            //    }
            //}
            // 等待命令执行完成
            exitCode = process.waitFor();
            //System.out.println("Exited with code : " + exitCode);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return new ExecShellRes(output,error,exitCode);
    }

    //use processBuilder exec shell commond
    /**
     * ByProcessBuilder
     */
    public  static ExecShellRes ByProcessBuilder(String commond)  {
        try {
            ProcessBuilder processBuilder = new ProcessBuilder(commond.split(" ")); //好处是,允许你设置命令的各个部分，而不是将整个命令作为一个字符串传递，这避免了shell注入攻击的风险。
            //parames type is :"ls", "a.txt"
            Process process = processBuilder.start();
            output = new BufferedReader(new InputStreamReader(process.getInputStream()));

            //while ((line = output.readLine()) != null) {
            //    System.out.println(line);
            //}
            //output.close();

            error = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            //if ((line = error.readLine()) != null){
            //    System.out.println("sout error:");
            //    while ((line = error.readLine()) != null) {
            //        System.out.println(line);
            //    }
            //}
            //error.close();
            int exitCode = process.waitFor();
            //System.out.println("Exited with code: " + exitCode);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return new ExecShellRes(output,error,exitCode);
    }
}
